home *** CD-ROM | disk | FTP | other *** search
/ POINT Software Programming / PPROG1.ISO / pascal / swag / textfile.swg / 0043_Binary Text File Access.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1995-03-26  |  4.9 KB  |  164 lines

  1. {
  2. From: tfiske@delphi.com (Todd Fiske)
  3.  
  4. I've got a huge unit that I've put together over the years that does this,
  5. but I'm not really ready to part with it. I'm happy to trade some tips
  6. though.
  7.  
  8. The easiest way to start is with text files under 64K, for which you don't
  9. have to worry about lines crossing the buffer boundary. Get the size of the
  10. file, then allocate an array on the heap of that size and blockread the file
  11. into it. Then use a function that reads from the current position up to the
  12. next CR and/or LF and returns all of that as a string. Here's a simple
  13. example of this:
  14.  
  15. {------------------------------------------------}
  16. {- bintext.pas - binary text file example       -}
  17. {- Todd Fiske (tfiske@delphi.com) - 09/28/1994  -}
  18. {------------------------------------------------}
  19. program bintext;
  20.  
  21. uses
  22.    dos;
  23.  
  24. const
  25.    CR = #13;
  26.    LF = #10;
  27.  
  28. {------------------------------------------------}
  29. {- input structure definition & base routines   -}
  30. {------------------------------------------------}
  31. type
  32.    big_array = array[0..65519] of byte;
  33.    big_ptr = ^big_array;
  34.    input_buffer = record
  35.       data : big_ptr;
  36.       size : word;
  37.       curr : word;
  38.    end;
  39.    input_ptr = ^input_buffer;
  40.  
  41. procedure start_input(var i : input_ptr; size : word);
  42. begin
  43.    if i = nil then begin
  44.       new(i);                          { create structure }
  45.       i^.size := size;
  46.       GetMem(i^.data, i^.size);        { create array (could test MemAvail) }
  47.       fillchar(i^.data^, i^.size, 0);  { initialize }
  48.       i^.curr := 0;
  49.    end;
  50. end;
  51. procedure stop_input(var i : input_ptr);
  52. begin
  53.    if i <> nil then begin
  54.       FreeMem(i^.data, i^.size);       { done with array }
  55.       dispose(i);                      { done with structure }
  56.       i := nil;
  57.    end;
  58. end;
  59. procedure load_input(i : input_ptr; s : string);
  60. var
  61.    f : file;
  62. begin
  63.    assign(f, s);                       { set filename }
  64.    reset(f, 1);                        { open with record length 1 }
  65.    blockread(f, i^.data^, i^.size);    { read in file - should test IOResult }
  66.    close(f);
  67. end;
  68.  
  69. {------------------------------------------------}
  70. {- low level access routines                    -}
  71. {------------------------------------------------}
  72. function curr_char(i : input_ptr) : char;
  73. begin
  74.    curr_char := char(i^.data^[i^.curr]);
  75. end;
  76. procedure next_char(i : input_ptr);
  77. begin
  78.    inc(i^.curr);
  79. end;
  80. function curr_pos(i : input_ptr) : word;
  81. begin
  82.    curr_pos := i^.curr;
  83. end;
  84. function end_of_input(i : input_ptr) : boolean;
  85. begin
  86.    end_of_input := i^.curr >= i^.size;
  87. end;
  88.  
  89. {------------------------------------------------}
  90. {- medium level access                          -}
  91. {------------------------------------------------}
  92. function get_line(i : input_ptr) : string;
  93. var
  94.    w   : string;
  95.    stt : word;
  96.    len : byte;
  97. begin
  98.    stt := curr_pos(i);
  99.    while (not (curr_char(i) in [CR, LF])) and (not end_of_input(i)) do
  100.       next_char(i);
  101.    {- testing for both CR and LF here allows reading of Unix files -}
  102.  
  103.    len := curr_pos(i) - stt;           { determine length read }
  104.    move(i^.data^[stt], w[1], len);     { copy into work string }
  105.    w[0] := char(len);                  { set work string length }
  106.  
  107.    if curr_char(i) = CR then next_char(i);  { skip line-end chars }
  108.    if curr_char(i) = LF then next_char(i);
  109.  
  110.    get_line := w;                      { return work string }
  111. end;
  112.  
  113. {------------------------------------------------}
  114. {- main program                                 -}
  115. {------------------------------------------------}
  116. var
  117.    sr   : SearchRec;
  118.    i    : input_ptr;
  119.    line : string;
  120.  
  121. begin
  122.    writeln;
  123.    writeln('BinText - binary textfile example');
  124.  
  125.    if paramcount = 0 then begin        { check command line }
  126.       writeln;
  127.       writeln('usage: bintext <filename>');
  128.       halt;
  129.    end;
  130.  
  131.    FindFirst(paramstr(1), AnyFile, sr); { test input file }
  132.    if DOSError <> 0 then begin
  133.       writeln(paramstr(1), ' not found');
  134.       halt;
  135.    end;
  136.    if sr.size > 65520 then begin
  137.       writeln(sr.name, ' : ', sr.size, ' bytes - too big (65520 bytes max)');
  138.       halt;
  139.    end;
  140.  
  141.    i := nil;                           { load, read, and close }
  142.    start_input(i, sr.size);
  143.    load_input(i, sr.name);
  144.  
  145.    while not end_of_input(i) do begin
  146.       line := get_line(i);
  147.       writeln(line);
  148.    end;
  149.  
  150.    stop_input(i);
  151. end.
  152. {------------------------------------------------}
  153. {- eof                                          -}
  154. {------------------------------------------------}
  155.  
  156. {
  157. This array-of-char file handling can be very flexible. I've included routines
  158. in my own to do things like skip whitespace, skip while in a particular groups
  159. of characters, skip until in a group of characters, get-while and get-until
  160. routines, etc. Another thing you can do is save the byte start position of each
  161. line, and jump right to that line by setting i^.curr. What's more, the same
  162. basic methods work on binary files as well.
  163. }
  164.